package com.heima.wemedia.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.heima.api.feign.ApArticleFeignClient;
import com.heima.audit.baidu.BaiduScan;
import com.heima.audit.tess4j.Tess4jClient;
import com.heima.file.service.FileStorageService;
import com.heima.model.article.dtos.ArticleDto;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.wemedia.pojos.WmChannel;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.model.wemedia.pojos.WmSensitive;
import com.heima.model.wemedia.pojos.WmUser;
import com.heima.utils.common.SensitiveWordUtil;
import com.heima.wemedia.service.*;
import lombok.extern.slf4j.Slf4j;
import net.sourceforge.tess4j.TesseractException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.imageio.ImageIO;
import javax.imageio.stream.ImageInputStream;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 文章自动审核服务实现类
 *
 * @Author mr.lin
 * @Date 2025/1/29 23:24
 */
@Service
@Slf4j
public class WmNewsAutoScanServiceImpl implements WmNewsAutoScanService {

    @Autowired
    private WmNewsService wmNewsService;

    @Autowired
    private BaiduScan baiduScan;

    @Autowired
    private FileStorageService fileStorageService;

    @Autowired
    private ApArticleFeignClient apArticleFeignClient;

    @Autowired
    private WmUserService wmUserService;

    @Autowired
    private WmchannelService wmchannelService;

    /**
     * 自媒体文章审核
     *
     * @param id 自媒体文章id
     */
    @Override
    @Transactional
    @Async // 异步线程调用
    public void autoScanWmNews(Integer id) {
        //1.查询自媒体文章数据
        WmNews wmNews = wmNewsService.getById(id);
        if (wmNews == null) {
            //没有此id对应的数据
            return;
        }
        //2.将文章数据中的文字 和 图片都抽取出来 放到一个map集合中
        Map<String, Object> textAndImageMap = getTextAndImage(wmNews);

        //2.2先去自定义的敏感词库中去过滤文章内容
        Boolean sensitiveTextResult = scanSensitiveText(textAndImageMap, wmNews);
        if (!sensitiveTextResult) {
            //如果结果是false ,代表内容审核没有通过
            return;
        }
        //3.调用百度云接口 对文章内容进行审核

        // 提示 1.合规 2.不合规 3.疑似 4.审核失败
        Boolean textResult = scanText(textAndImageMap, wmNews);
        if (!textResult) {
            //如果结果是false ,代表内容审核没有通过
            return;
        }
        //4.调用百度云接口 对文章的图片进行审核
        Boolean imageResult = scanImages(textAndImageMap, wmNews);
        if (!imageResult) {
            //如果结果是false ,代表图片审核没有通过
            return;
        }
        //如果能走到这,就嗲代表审核通过了
        //5.调用feign接口,保存文章数据到 leadnews_article 数据库的三表中
        ResponseResult responseResult = saveArticle(wmNews);
        if (!responseResult.getCode().equals(200)) {
            throw new RuntimeException("WmNewsAutoScanServiceImpl-文章审核，保存app端相关文章数据失败");
        }
        //6.修改自媒体的文章审核状态
        //将article_id设置一下
        wmNews.setArticleId(Long.valueOf(responseResult.getData().toString()));
        wmNews.setStatus((short) 8); //审核通过,待发布
        wmNews.setReason("审核通过!");
        wmNews.setCreatedTime(new Date());
        updateWmNewsStatusAndReason(wmNews);//更新文章操作
    }

    @Autowired
    private WmSensitiveService wmSensitiveService;

    /**
     * 文章内容审核--自定义敏感词库
     *
     * @param textAndImageMap
     * @param wmNews
     * @return
     */
    private Boolean scanSensitiveText(Map<String, Object> textAndImageMap, WmNews wmNews) {

        Boolean flag = true;
        //1.查询敏感词库列表
        List<WmSensitive> wmSensitiveList = wmSensitiveService.list();
        if (CollectionUtils.isEmpty(wmSensitiveList)) {
            log.info("敏感词库列表为空");
            return flag;
        }
        //2.stream流过滤,只要敏感词
        List<String> sensitiveList = wmSensitiveList.stream().map(WmSensitive::getSensitives).collect(Collectors.toList());

        //3.调用敏感词工具类.初始化敏感词的map集合
        SensitiveWordUtil.initMap(sensitiveList);
        //4.进行文字审核
        Map<String, Integer> resultMap = SensitiveWordUtil.matchWords(textAndImageMap.get("text").toString());
        if (resultMap != null && resultMap.size() > 0) {
            flag = false;
            wmNews.setStatus((short) 2); // 审核失败
            wmNews.setReason("文章内容包含敏感词!!");
            //更新文章审核数据
            updateWmNewsStatusAndReason(wmNews);
        }
        return flag;
    }

    private ResponseResult saveArticle(WmNews wmNews) {
        ArticleDto article = new ArticleDto();
        BeanUtils.copyProperties(wmNews, article);
        //补全不能拷贝的字段
        // userId = 作者id 作者名字
        article.setAuthorId(wmNews.getUserId().longValue());
        WmUser wmUser = wmUserService.getById(wmNews.getUserId());
        article.setAuthorName(wmUser.getName());
        // 频道名字
        WmChannel wmChannel = wmchannelService.getById(wmNews.getChannelId());
        article.setChannelName(wmChannel.getName());
        // 文章布局 type = layout
        article.setLayout(wmNews.getType());
        return apArticleFeignClient.saveArticle(article);
    }

    @Autowired
    private Tess4jClient tess4jClient;

    private Boolean scanImages(Map<String, Object> textAndImageMap, WmNews wmNews) {

        //定义一个布尔值
        Boolean flag = true; //默认
        List<String> imageList = (List<String>) textAndImageMap.get("image");
        if (CollectionUtils.isNotEmpty(imageList)) {
            for (String image : imageList) {
                //下载图片,获取字节码
                byte[] bytes = fileStorageService.downLoadFile(image);


                //调用自定义Tess4j客户端,利用OCR技术对图片的文字进行提取审核
                ByteArrayInputStream input = new ByteArrayInputStream(bytes);
                try {
                    BufferedImage bufferedImage = ImageIO.read(input);
                    String imageText = tess4jClient.doOCR(bufferedImage);
                    if (imageText != null) {
                        Map<String, Object> map = new HashMap<>();
                        map.put("text", imageText);
                        flag = scanSensitiveText(map, wmNews);
                        if (!flag) {
                            //如果结果是false ,代表内容审核没有通过
                            return flag;
                        }
                    }

                } catch (Exception e) {
                    e.printStackTrace();
                    return false;
                }


                //调用百度云接口 对文章的图片进行审核
                Integer imageResult = baiduScan.imageScan(bytes);
                if (imageResult == 2) {
                    wmNews.setStatus((short) 2); // 审核失败
                    wmNews.setReason("图片有违规信息!!");
                    flag = false;
                } else if (imageResult == 3) {
                    wmNews.setStatus((short) 3); // 疑似有违规内容
                    wmNews.setReason("图片疑似有违规信息!,请通过人工审核");
                    flag = false;
                } else if (imageResult == 4) {
                    wmNews.setStatus((short) 2); // 审核失败
                    wmNews.setReason("图片审核失败");
                    flag = false;
                }
                if (!flag) {
                    //更新文章审核数据
                    updateWmNewsStatusAndReason(wmNews);
                }
            }
        }
        return flag;
    }

    /**
     * 文章内容审核
     *
     * @param textAndImageMap
     * @param wmNews
     * @return
     */
    private Boolean scanText(Map<String, Object> textAndImageMap, WmNews wmNews) {
        Integer textResult = baiduScan.textScan(textAndImageMap.get("text").toString());

        //定义一个布尔值
        Boolean flag = true; //默认
        if (textResult == 2) {
            wmNews.setStatus((short) 2); // 审核失败
            wmNews.setReason("文章内容有违规内容!!");
            flag = false;
        } else if (textResult == 3) {
            wmNews.setStatus((short) 3); // 疑似有违规内容
            wmNews.setReason("文章内容疑似有违规内容!,请通过人工审核");
            flag = false;
        } else if (textResult == 4) {
            wmNews.setStatus((short) 2); // 审核失败
            wmNews.setReason("文章内容审核失败");
            flag = false;
        }
        if (!flag) {
            //更新文章审核数据
            updateWmNewsStatusAndReason(wmNews);
        }
        return flag;
    }

    /**
     * 更新文章审核 状态和 原因
     *
     * @param wmNews
     */
    private void updateWmNewsStatusAndReason(WmNews wmNews) {
        /*boolean flag = wmNewsService.lambdaUpdate().eq(WmNews::getId, wmNews.getId())
                .set(WmNews::getStatus, wmNews.getStatus())
                .set(WmNews::getReason, wmNews.getReason())
                .update();*/
        boolean flag = wmNewsService.updateById(wmNews);
        if (!flag) {
            throw new RuntimeException("更新文章审核状态和原因失败");
        }
    }

    /**
     * 获取文章内容中的图片和文本内容
     *
     * @param wmNews
     * @return
     */
    private Map<String, Object> getTextAndImage(WmNews wmNews) {

        //创建一个存放图片的集合
        List<String> imageList = new ArrayList<>();

        //先把wmNews中images图片获取出来
        String images = wmNews.getImages();
        String[] split = null;
        if (images != null) {
            //这个如果有多个图片,用的逗号隔开的
            split = images.split(",");
        }
        if (split != null) {
            imageList.addAll(Arrays.asList(split));
        }
        //创建一个存放文本内容的集合
        StringBuilder textStringBuilder = new StringBuilder();
        String title = wmNews.getTitle(); // 标题内容
        String labels = wmNews.getLabels(); // 标签内容
        textStringBuilder.append(title).append(labels);
        String contentJsonStr = wmNews.getContent(); // json类型的内容字符串(包含内容+图片)
        //将内容和图片分别提取出来
        List<Map> listContent = JSON.parseArray(contentJsonStr, Map.class);
        if (CollectionUtils.isNotEmpty(listContent)) {
            for (Map mapContent : listContent) {
                if ("text".equals((String) mapContent.get("type"))) {
                    //是 文本类型就拼接进去
                    textStringBuilder.append(mapContent.get("value"));
                }
                if ("image".equals((String) mapContent.get("type"))) {
                    //是 图片类型就放到集合中
                    imageList.add(mapContent.get("value").toString());
                }
            }
        }
        //对图片路径进行去重
        imageList = imageList.stream().distinct().collect(Collectors.toList());
        Map<String, Object> map = new HashMap<>();
        map.put("text", textStringBuilder.toString());
        map.put("image", imageList);
        return map;
    }


}
